module DBS (DBS (DBS), DBS.empty, ID, getLastFilmId, setLastFilmId,
             getLastClientId, setLastClientId, 
	     getLastLoanId, setLastLoanId,
             getFilms, setFilms, 
             getClients, setClients, 
	     getLoans, setLoans,
             selectFilmBy, selectFilm, 
             selectClientBy, selectClient,
	     selectLoanBy, selectLoan,
             loadFromFile, saveToFile)  where

import Film
import Client
import IdObject
import Loan

type ID = Int

data DBS = DBS ID [Film] ID [Client] ID [Loan] deriving (Show, Read)
empty :: DBS
empty = DBS 0 [] 0 [] 0 []

{- Films -}
getLastFilmId :: DBS -> ID
getLastFilmId (DBS i _ _ _ _ _) = i

setLastFilmId :: ID -> DBS -> DBS
setLastFilmId j (DBS fi fl ci cl li ll) = (DBS j fl ci cl li ll)

getLastClientId :: DBS -> ID
getLastClientId (DBS _ _ i _ _ _) = i

setLastClientId :: ID -> DBS -> DBS
setLastClientId j (DBS fi fl ci cl li ll) = (DBS fi fl j cl li ll)

getLastLoanId :: DBS -> ID
getLastLoanId (DBS _ _ _ _ i _) = i

setLastLoanId :: ID -> DBS -> DBS
setLastLoanId j (DBS fi fl ci cl li ll) = (DBS fi fl ci cl j ll)

getFilms :: DBS -> [Film]
getFilms (DBS _ f _ _ _ _) = f

setFilms :: [Film] -> DBS -> DBS
setFilms as (DBS fi fl ci cl li ll) = (DBS fi as ci cl li ll)

{- Clients -}
getClients :: DBS -> [Client]
getClients (DBS _ _ _ cl _ _) = cl

setClients :: [Client] -> DBS -> DBS
setClients as (DBS fi fl ci cl li ll) = (DBS fi fl ci as li ll)

selectFilmBy :: (Film -> Bool) -> DBS -> [Film]
selectFilmBy f db = filter f (getFilms db)

selectFilm :: ID -> DBS -> Film
selectFilm i db =
    head (selectFilmBy ((== i).getId) db)


selectClientBy :: (Client -> Bool) -> DBS -> [Client]
selectClientBy f db = filter f (getClients db)

selectClient :: ID -> DBS -> Client
selectClient i db =
    head (selectClientBy ((== i).getId) db)

{- Loans -}
getLoans :: DBS -> [Loan]
getLoans (DBS fi fl ci cl li ll) = ll

setLoans :: [Loan] -> DBS -> DBS
setLoans as (DBS fi fl ci cl li ll) = (DBS fi fl ci cl li as)

selectLoan :: ID -> DBS -> Loan
selectLoan i db =
    head (selectLoanBy ((== i).getId) db)

selectLoanBy :: (Loan -> Bool) -> DBS -> [Loan]
selectLoanBy f db = filter f (getLoans db)

{- load & save -}
loadFromFile :: String -> IO DBS
loadFromFile filename = 
        catch (do
                s <- readFile filename
                return ((read s)::DBS)
        ) errorHandler
        where errorHandler e = 
                catch (do
                        putStrLn ("Cannot read file "++ filename ++ ", trying to create new one\n")
                        writeFile filename (show DBS.empty)
                        return DBS.empty) errorHandler2
                where errorHandler2 e2 = do
                        putStrLn ("Cannot read file "++ filename ++ " and cannot create new\n")
                        ioError e2


saveToFile :: String -> DBS -> IO ()
saveToFile filename db = 
        catch (do
                let str = show db
                seq (length str) (writeFile filename str)
                return ()) errorHandler
         where errorHandler e = do 
                putStrLn ("Cannot write to file "++ filename ++ "\n")
                ioError e
